import asyncio
import json
from textwrap import dedent
from typing import Any

import requests
from agno.agent import Agent
from agno.db.sqlite import SqliteDb
from agno.models.openai import OpenAIChat, OpenAILike
from agno.team import Team
from agno.tools.baidusearch import BaiduSearchTools
from agno.tools import tool
from agno.tools.workflow import WorkflowTools
from agno.workflow.types import StepInput, StepOutput
from agno.workflow.workflow import Workflow
from bs4 import BeautifulSoup

from configs.basic_config import ALI_GENERATION_MODEL, AGENT_URL, ALI_DASHSCOPE_API_KEY

FEW_SHOT_EXAMPLES = dedent("""\
    你可以参考以下示例，了解如何使用每个工具。

    ### 示例1：博客文章工作流
    用户：请围绕主题"2024年人工智能趋势"撰写一篇博客文章
    执行：input: {"input_data": "2024年人工智能趋势", "additional_data": "{\"topic\": \"人工智能、AI智能体、AI工作流\", \"style\": \"博客文章应通俗易懂、条理清晰\"}"}
    最终回答：我已通过工作流完成关于"2024年人工智能趋势"的博客文章。文章内容如下……

    ### 示例2：科技主题文章
    用户：写一篇关于机器学习的科普文章
    执行：input: {"input_data": "机器学习科普", "additional_data": "{\"topic\": \"机器学习基础概念、算法应用、未来发展\", \"style\": \"科普文章要生动有趣、通俗易懂\"}"}

    ### 示例3：技术教程
    用户：写一篇Python编程入门教程
    执行：input: {"input_data": "Python编程入门", "additional_data": "{\"topic\": \"Python基础语法、数据类型、函数使用\", \"style\": \"教程要步骤清晰、有代码示例\"}"}

    重要提示：
    - 使用 input 参数，包含 input_data 和 additional_data
    - additional_data 需要是 JSON 字符串格式
    - 必须使用 additional_data 来传递主题和写作风格
""")


# --- 使用 @tool 装饰器封装 Bocha 搜索工具 ---
@tool(stop_after_tool_call=True)
def bocha_web_search(query: str) -> str:
    """执行bocha网络搜索并返回格式化结果

    Args:
        query: 搜索查询词

    Returns:
        格式化的搜索结果字符串
    """
    print(f"🔍 正在搜索: {query}")

    def get_search_results(search_query):
        """发送POST请求，获取web搜索结果"""
        url = "https://api.bochaai.com/v1/web-search"
        payload = json.dumps({
            "query": search_query,
            "summary": True,
            "freshness": "noLimit",
            "count": 8
        })
        headers = {
            'Authorization': 'Bearer sk-5e5970a6779d48959e5294489c7dec8e',
            'Content-Type': 'application/json'
        }

        try:
            response = requests.post(url, headers=headers, data=payload, timeout=10)
            if response.status_code == 200:
                return response.json()
            else:
                print(f"请求失败，状态码：{response.status_code}, 响应: {response.text}")
                return None
        except requests.exceptions.RequestException as e:
            print(f"请求过程中发生网络错误: {e}")
            return None

    def get_page_content(url):
        """抓取网页内容"""
        try:
            response = requests.get(url, timeout=10)
            if response.status_code == 200:
                soup = BeautifulSoup(response.text, 'html.parser')
                text = soup.get_text()
                text = ' '.join(text.split())
                return text[:1500]
            else:
                print(f"无法访问页面: {url}，状态码: {response.status_code}")
                return None
        except Exception as e:
            print(f"抓取页面内容时出错: {e}")
            return None

    search_results = get_search_results(query)
    if search_results and 'data' in search_results:
        results = []
        web_pages = search_results['data'].get('webPages', {}).get('value', [])

        for i, item in enumerate(web_pages, 1):
            url = item.get('url', '')
            title = item.get('title', '无标题')
            summary = item.get('summary', '无摘要')

            if summary and summary != '无摘要':
                content = summary
            else:
                print(f"   📥 摘要为空，正在抓取网页内容: {url}")
                content = get_page_content(url) or "无法获取内容"

            result_text = f"""
            📰 搜索结果 {i}:
            🏷️ 标题: {title}
            🔗 网址: {url}
            📝 内容: {content}
            """
            results.append(result_text)

        if results:
            final_result = "\n".join(results)
            print(f"[DEBUG] 博查搜索完成，总结果长度: {len(final_result)} 字符")
            return final_result
        else:
            return "网络搜索未找到相关信息"
    else:
        error_msg = "网络搜索请求失败或没有结果"
        print(f"[ERROR] {error_msg}")
        return error_msg


# --- 定义代理 ---

# 创建包含 Bocha 搜索工具的代理
bocha_search_agent = Agent(
    name="Bocha搜索代理",
    model=OpenAILike(id=ALI_GENERATION_MODEL, name=ALI_GENERATION_MODEL, api_key=ALI_DASHSCOPE_API_KEY,
                     base_url=AGENT_URL),
    tools=[bocha_web_search],
    role="从Bocha搜索结果中提取关键见解和内容",
    instructions="使用Bocha搜索引擎获取最新的网络信息",
)

baidu_search_agent = Agent(
    name="百度搜索代理",
    model=OpenAILike(id=ALI_GENERATION_MODEL, name=ALI_GENERATION_MODEL, api_key=ALI_DASHSCOPE_API_KEY,
                     base_url=AGENT_URL),
    tools=[BaiduSearchTools(fixed_max_results=10,fixed_language="汉语")],
    role="从百度搜索结果中提取关键见解和内容",
    # debug_mode=True,
)

writer_agent = Agent(
    name="写作代理",
    model=OpenAILike(id=ALI_GENERATION_MODEL, name=ALI_GENERATION_MODEL, api_key=ALI_DASHSCOPE_API_KEY,
                     base_url=AGENT_URL),
    instructions="围绕指定主题撰写一篇博客文章",
    # stream=True,
    # debug_mode=True,
)


def prepare_input_for_web_search(step_input: StepInput) -> StepOutput:
    """准备搜索输入"""
    # 统一处理输入
    print("prepare_input_for_web_search: ")
    print(step_input)
    if not step_input.input:
        return StepOutput(content="错误：未提供输入数据", success=False)

    # 提取输入数据
    if isinstance(step_input.input, dict):
        input_data = step_input.input.get('input_data', '')
        additional_data = step_input.input.get('additional_data', {})
    else:
        # 如果是字符串，直接作为 input_data
        input_data = str(step_input.input)
        additional_data_str = step_input.additional_data or {}
        additional_data = json.loads(additional_data_str)

    topic = additional_data.get('topic', '')
    return StepOutput(
        content=dedent(f"""\
                我正在撰写一篇标题为：{input_data} 的博客文章
                <主题>
                {topic}
                </主题>
                请至少搜索10篇相关文章\
                """)
    )


def prepare_input_for_writer(step_input: StepInput) -> StepOutput:
    """准备写作输入"""
    # 统一处理输入
    print("prepare_input_for_writer: ")
    print(step_input)
    if not step_input.input:
        return StepOutput(content="错误：未提供输入数据", success=False)

    # 提取附加数据
    if isinstance(step_input.input, dict):
        additional_data = step_input.input.get('additional_data', {})
    else:
        input_data = str(step_input.input)
        additional_data_str = step_input.additional_data or {}
        try:
            additional_data = json.loads(additional_data_str)
        except json.JSONDecodeError:
            additional_data = {}

    # title = additional_data.get('title', '')
    topic = additional_data.get('topic', '')
    style = additional_data.get('style', '')
    research_team_output = step_input.previous_step_content or ""
    print("research_team_output length: ")
    print(len(research_team_output))
    return StepOutput(
        content=dedent(f"""\
                我正在撰写一篇标题为：{input_data} 的博客文章
                <要求风格>
                {style}
                </要求风格>
                <主题>
                {topic}
                </主题>
                以下是来自网络的信息：
                <调研结果>
                {research_team_output}
                </调研结果>\
                """)
    )


# 定义研究团队，用于复杂分析
research_team = Team(
    name="研究团队",
    members=[baidu_search_agent], #bocha_search_agent
    model=OpenAILike(id=ALI_GENERATION_MODEL, name=ALI_GENERATION_MODEL, api_key=ALI_DASHSCOPE_API_KEY,
                     base_url=AGENT_URL),
    instructions="从百度搜索结果中调研科技类主题",
    # debug_mode=True,
)

content_creation_workflow = Workflow(
    name="博客文章生成工作流",
    description="自动从百度搜索结果生成博客文章",
    # db=SqliteDb(
    #     session_table="workflow_session",
    #     db_file="tmp/workflow.db",
    # ),
    steps=[
        prepare_input_for_web_search,
        research_team,
        prepare_input_for_writer,
        writer_agent,
    ],
    # debug_mode=True,

    # stream_intermediate_steps=True, 这样设置主代理会报错- WorkflowTools
    # stream=True
)


# 创建主代理
agent = Agent(
    model=OpenAILike(id=ALI_GENERATION_MODEL, name=ALI_GENERATION_MODEL, api_key=ALI_DASHSCOPE_API_KEY,
                     base_url=AGENT_URL),
    tools=[WorkflowTools(workflow=content_creation_workflow, add_few_shot=False,
                         few_shot_examples=FEW_SHOT_EXAMPLES, enable_think=False, enable_analyze=False)],
    #async_mode=True,
    stream=True,
    markdown=True,
    instructions=dedent("""\
        你是一个专业的博客文章写作助手。当你收到写作请求时，请使用 run_workflow 工具来生成文章。

        ## 工具使用方法：

        ### run_workflow 工具参数：
        使用 input 参数，包含：
        {
            "input_data": "文章标题",
            "additional_data": "{\"topic\": \"具体的主题内容描述\", \"style\": \"文章的风格要求\"}"
        }

        ### 使用示例：
        用户：请写一篇关于量子计算的文章
        你应该使用：{"input_data": "量子计算", "additional_data": "{\"topic\": \"量子计算原理、应用场景、发展前景\", \"style\": \"技术文章要专业准确\"}"}

        用户：写一篇AI技术的科普文章
        你应该使用：{"input_data": "AI技术科普", "additional_data": "{\"topic\": \"人工智能基础、机器学习、深度学习\", \"style\": \"科普文章要通俗易懂\"}"}

        ## 重要提醒：
        1. additional_data 必须是有效的 JSON 字符串（需要转义双引号）
        2. topic 字段是必需的
        3. 根据用户需求调整 topic 和 style 的内容
    """),
)

# 创建直接使用 Bocha 搜索的独立代理
# direct_search_agent = Agent(
#     model=OpenAILike(id=ALI_GENERATION_MODEL, name=ALI_GENERATION_MODEL, api_key=ALI_DASHSCOPE_API_KEY,
#                      base_url=AGENT_URL),
#     tools=[bocha_web_search],
#     markdown=True,
# )

asyncio.run(agent.aprint_response(
    "请撰写一篇标题为《2025年量子计算》的博客文章",
    # instructions="When you run the workflow using the `run_workflow` tool, remember to pass `additional_data` as a dictionary of key-value pairs.",
    # stream=True,
    debug_mode=True,
))


# # For async workflow execution
# workflow_tools = WorkflowTools(
#     workflow=content_creation_workflow,
#     async_mode=True,  # This will use async versions of the tools
#     enable_run_workflow=True,
# )
#
# agent = Agent(
#     model=OpenAILike(id=ALI_GENERATION_MODEL, name=ALI_GENERATION_MODEL, api_key=ALI_DASHSCOPE_API_KEY,
#                              base_url=AGENT_URL),
#     tools=[workflow_tools],
# )
#
# await agent.arun(...)